﻿/*
 * Created by SharpDevelop.
 * User: delmore
 * Date: 6/1/2014
 * Time: 2:29 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Configuration;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

using InstallationWrapper.Engine;

namespace InstallationWrapper
{
	/// <summary>
	/// Description of UIForm.
	/// </summary>
	public partial class UIForm : Form
	{
		#region Private Variables
		/// <summary>
		/// Wrapper Engine variable initialized by a singleton instance
		/// </summary>
		private WrapperEngine engine;
		
		/// <summary>
		/// Access UI components accross threads
		/// </summary>
		private SynchronizationContext synchronizationContext ;
		
		/// <summary>
		/// Full window text box used for displaying information
		/// </summary>
		private TextBox fullWindowTextBox;
		
		private string uiLevel;
		#endregion
		
		/// <summary>
		/// Enables debug messages for development only
		/// </summary>
		private const bool   DEBUG_APPLICATION = false;
		private const string UILEVEL_BASIC     = "basic";
		private const string UILEVEL_NONE      = "none";
		private const string UILEVEL_FULL      = "full";
		public UIForm()
		{
			//
			// The InitializeComponent() call is required for Windows Forms designer support.
			//
			InitializeComponent();
			Init();
		}
		
		#region Methods
		void Init()
		{
			synchronizationContext = SynchronizationContext.Current;
			uiLevel = ConfigurationManager.AppSettings["UserInterfaceLevel"].ToLower();
			switch(uiLevel.ToLower())
			{
				case "basic":
					SetWindowToBasic();
					break;
				case "full":
					SetWindowToFull();
					break;
				default:
					break;
			}
			
			//Set window title if property field else default
			var title = ConfigurationManager.AppSettings["WindowTitle"];
			if(!string.IsNullOrEmpty(title))
				this.Text = title;
			
			
			engine = WrapperEngine.Instance;
			//Route event by event status
			engine.Update += (obj,evt) =>
			{
				switch(evt.EventType)
				{
					case Status.Completed:
						ProcedureCompleted(evt.Message);
						break;
					case Status.Failed:
						ProcedureFailed(evt.Message);
						break;
					case Status.Starting:
						WrapperEngineStarting();
						break;
					case Status.Running:
						ProcedureRunning();
						break;
					default:
						UpdateUI();
						break;
				}
			};
			engine.Start();
		}
		
		void SetWindowToBasic()
		{
			this.Visible = true;
			this.Size = new Size(336, 100);
		}
		
		void SetWindowToFull()
		{
			//Configure Full Window Textbox
			fullWindowTextBox = new TextBox();
			fullWindowTextBox.Multiline = true;
			fullWindowTextBox.ReadOnly = true;
			fullWindowTextBox.BackColor = Color.Black;
			fullWindowTextBox.ForeColor = Color.White;
			fullWindowTextBox.Size = new Size(305,200);
			fullWindowTextBox.Location = new Point(13,60);
			
			WriteLogMessage("Random Execute\r\nWritten by: Darrell Elmore\r\n",null,MessageLevel.Normal);
			
			this.Size = new Size(336,300);
			this.Controls.Add(fullWindowTextBox);
			this.Visible = true;
		}
		
		/// <summary>
		/// Executed upon process completition
		/// </summary>
		/// <param name="message">Message sent from Wrapper Engine</param>
		void ProcedureCompleted(string message)
		{
			WriteLogMessage(message, "Completed");
            engine.Dispose();
			Application.Exit();
		}
		
		/// <summary>
		/// Executed upon process failure
		/// </summary>
		/// <param name="message">Message sent from Wrapper Engine</param>
		void ProcedureFailed(string message)
		{
			WriteLogMessage(message, "Failure");
		}
		
		/// <summary>
		/// Executed when process is running
		/// </summary>
		void ProcedureRunning()
		{
			WriteLogMessage(engine.FileName + " " + engine.Arguments, "Starting");
		}
		
		/// <summary>
		/// Executed when Wrapper Engine is starting
		/// </summary>
		void WrapperEngineStarting()
		{
			synchronizationContext.Send(
				(d) =>
				{
					progressBar.Maximum = progressBar.Value = engine.RandomStartTimeInSeconds;
					remainingTimeLabel.Text = string.Format("Time Until Execution: {0}", GetTimeLeft());
				},null);
		}
		
		/// <summary>
		/// Called when wrapper engine has updated information
		/// </summary>
		void UpdateUI()
		{
			synchronizationContext.Send(
				(d) =>
				{
					remainingTimeLabel.Text = string.Format("Time Until Execution: {0}", GetTimeLeft());
					progressBar.Value = engine.TimeRemainingInSeconds;
					progressBar.Update();
				},null);
		}
		
		/// <summary>
		/// Returns a string with the amount of time left before process execution
		/// </summary>
		string GetTimeLeft()
		{
			return TimeSpan.FromSeconds(engine.TimeRemainingInSeconds).ToString();
		}
		
		/// <summary>
		/// When DEBUG is true displays message in console
		/// </summary>
		/// <param name="message">Message to display</param>
		/// <param name="category">Message category
		/// </param>
		void WriteLogMessage(string message, string category)
		{
			System.Diagnostics.Debug.WriteLineIf(DEBUG_APPLICATION, message, category);
		}
		
		void WriteLogMessage(string message, string category, MessageLevel level)
		{
			if(uiLevel.Equals(UILEVEL_FULL))
			{
				synchronizationContext.Send(
					(d)=>
					{
						if(level == MessageLevel.Normal)
							fullWindowTextBox.Text += string.Format("{1}\r\n",category,message);
						else
							fullWindowTextBox.Text += string.Format("{0}: {1} [{2}]\r\n",category,message,DateTime.Now);
						fullWindowTextBox.Select(0,0);
					},null);
			}
		}
		#endregion
	}
	
	public enum MessageLevel
	{
		Important,
		Normal
	}
}
